﻿using Magicodes.ExporterAndImporter.Core.Models;
using Magicodes.ExporterAndImporter.Pdf;
using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WkHtmlToPdfDotNet;

namespace BuddHa.Common.FileExportOpex.Pdf
{
    [PdfExporter(Orientation = Orientation.Portrait)]
    public abstract class ExportModel
    {
        public ExportModel()
        {
            var pathArray = new List<string>();
            pathArray.Add(AppDomain.CurrentDomain.BaseDirectory);
            var t = GetType();
            pathArray.AddRange(t.Namespace.Replace("BuddHa.Common", "").Split('.'));
            pathArray.Add("TemplateFiles");
            pathArray.Add(t.Name.TrimEnd("Model".ToArray()) + ".cshtml");

            DefaultTemplatePath = Path.Combine(pathArray.ToArray());
        }

        public string DefaultTemplatePath
        {
            get; private set;
        }

        public abstract string CreateExportPath(string pathHeader = "");

        public abstract string CreateFileName(string fileName = "");

        public virtual Task<ExportFileInfo> Export(string outputFilePath = "")
        {
            if (string.IsNullOrWhiteSpace(outputFilePath))
            {
                outputFilePath = Path.Combine(CreateExportPath(), CreateFileName());
            }
            return Export(DefaultTemplatePath, outputFilePath);
        }

        public virtual async Task<ExportFileInfo> Export(string templateFilePath, string outputFilePath)
        {
            if (!File.Exists(templateFilePath))
            {
                throw new FileNotFoundException(templateFilePath);
            }
            if (string.IsNullOrWhiteSpace(outputFilePath))
            {
                outputFilePath = Path.Combine(CreateExportPath(), CreateFileName());
            }
            try
            {
                var fileInfo = new FileInfo(outputFilePath);
                if (!fileInfo.Directory.Exists)
                {
                    fileInfo.Directory.Create();
                }
                if (fileInfo.Exists)
                {
                    fileInfo.Delete();
                }
                var template = await File.ReadAllTextAsync(templateFilePath);
                var exporter = new PdfExporter();
                var result = await exporter.ExportByTemplate(outputFilePath, this, template);
                return result;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public async Task<ExportFileInfo> ExportZip(IEnumerable<ExportModel> exportModels, string fileName = "", string pathHeader = "", string zipFileName = "")
        {
            try
            {
                if (exportModels == null || !exportModels.Any())
                {
                    throw new ArgumentNullException("参数exportModels异常，导出失败");
                }
                if (string.IsNullOrWhiteSpace(pathHeader))
                {
                    pathHeader = CreateExportPath(pathHeader);
                }
                if (string.IsNullOrWhiteSpace(zipFileName))
                {
                    zipFileName = CreateFileName().Split('.')[0];
                }
                var zipDirectoryPath = Path.Combine(pathHeader, zipFileName);
                var zipFilePath = Path.Combine(pathHeader, zipFileName + ".zip");
                if (File.Exists(zipFilePath))
                {
                    File.Delete(zipFilePath);
                }
                var zipDirectory = Directory.CreateDirectory(zipDirectoryPath);
                foreach (var item in exportModels)
                {
                    await item.Export(Path.Combine(zipDirectoryPath, item.CreateFileName(fileName)));
                }

                ZipFile.CreateFromDirectory(zipDirectoryPath, zipFilePath);
                zipDirectory.Delete(true);
                return new ExportFileInfo()
                {
                    FileName = zipFilePath,
                    FileType = "zip"
                };
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}
